package com.andnnl.ratelimit;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import com.google.common.util.concurrent.RateLimiter;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * Created by chenss on 2020/8/27.
 */
public class RateLimiterTest {
    public static void main(String[] args) {
        testAcquire();
//        testAcquire2();//测试每秒sleep 600次
    }

    public static void testAcquire() {
        //首先通过RateLimiter.create(1);创建一个限流器，参数代表每秒生成的令牌数，通过limiter.acquire(i);
        // 来以阻塞的方式获取令牌，当然也可以通过tryAcquire(int permits, long timeout, TimeUnit unit)
        // 来设置等待超时时间的方式获取令牌，如果超timeout为0，则代表非阻塞，获取不到立即返回。
        RateLimiter limiter = RateLimiter.create(300,0, TimeUnit.MILLISECONDS);//平滑限流
//        RateLimiter limiter = RateLimiter.create(300);//第一秒，瞬时流速是设置的2倍，变成瞬时过高。

        ThreadUtil.sleep(1000);
        int k = 0;
        long t1 = System.currentTimeMillis();
        for (int i = 1; i < 200000; i = i + 1) {
            int x = RandomUtil.randomInt(1, 10);
            double waitTime = limiter.acquire(x);
            //System.out.println("cutTime=" + System.currentTimeMillis() + " acq:" + i + " waitTime:" + waitTime);
            if(i % 1000 == 0){
                limiter.setRate(1000);
                System.out.println("cutTime=" + System.currentTimeMillis() + "   " + new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(new Date()));
            }
            k += x;
            long t2 = System.currentTimeMillis();
            if (t2 - t1 > 1000) {
                System.out.println("k ->" + k + " x ->" + x + "  t2-t1->" + (t2 - t1));
                k = 0;
                t1 = t2;
            }
        }
    }


    public static void testAcquire2() {
        //首先通过RateLimiter.create(1);创建一个限流器，参数代表每秒生成的令牌数，通过limiter.acquire(i);
        // 来以阻塞的方式获取令牌，当然也可以通过tryAcquire(int permits, long timeout, TimeUnit unit)
        // 来设置等待超时时间的方式获取令牌，如果超timeout为0，则代表非阻塞，获取不到立即返回。
        System.out.println("cutTime=" + System.currentTimeMillis() + "   " + new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(new Date()));
        int permitsPerSecond = 1;
        RateLimiter limiter = RateLimiter.create(permitsPerSecond);

        long t1 = System.currentTimeMillis();
        for (int i = 1; i <= 10; i = i + 1) {
            double waitTime = limiter.acquire(1);
            System.out.println("cutTime=" + System.currentTimeMillis() + "   " + new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(new Date()) + " acq:" + i + " waitTime:" + waitTime);
            if (i % 5 == 0) {
                limiter.setRate(5);
                System.out.println(limiter.getRate());
            }

//            limiter.setRate(permitsPerSecond);
        }
        long t2 = System.currentTimeMillis();
        System.out.println("total:" + (t2 - t1));
    }
}
